#!/usr/bin/env python3.9
# -*- encoding: utf-8 -*-
"""
@文件        :common.py
@说明        : 通用函数
@时间        :2022/12/01 12:58:03
@作者        :Mars
@版本        :1.0
"""
import base64
import datetime
import json
import logging
import os
import time
import uuid

import requests
import yaml
from Crypto.Cipher import AES, ARC4
from django.http import HttpResponse
from openpyxl import Workbook

# 获取在配置文件中定义的logger，用来记录日志
logger = logging.getLogger("django")


class PrpCrypt(object):
    def __init__(self, key):
        self.key = key.encode("utf-8")
        self.mode = AES.MODE_CBC
        # 这里使用的16个1作为iv,亦可动态生成可变iv
        self.iv = "1111111111111111".encode("utf-8")

    def encrypt(self, text):
        text = text.encode("utf-8")
        cryptor = AES.new(self.key, self.mode, self.iv)
        # 这里密钥key 长度必须为16（AES-128）,
        # 24（AES-192）,或者32 （AES-256）Bytes 长度
        # 目前AES-128 足够目前使用
        length = 16
        count = len(text)
        if count < length:
            add = length - count
            # \0 backspace
            # text = text + ('\0' * add)
            text = text + ("\01" * add).encode("utf-8")
        elif count > length:
            add = length - (count % length)
            # text = text + ('\0' * add)
            text = text + ("\01" * add).encode("utf-8")
        a = cryptor.encrypt(text)
        self.ciphertext = self.iv + a
        # 因为AES加密时候得到的字符串不一定是ascii字符集的，输出到终端或者保存时候可能存在问题
        # 所以这里统一把加密后的字符串转化为base64
        return str(base64.b64encode(self.ciphertext), "utf-8")

    def decrypt(self, text):
        iv = base64.b64decode(text)[0:16]
        encry_text = base64.b64decode(text)[16:]
        cryptor = AES.new(self.key, self.mode, iv)
        plain_text = cryptor.decrypt(encry_text)
        # return plain_text.rstrip('\0')
        return str(plain_text, "utf-8").rstrip("\01")


# 单例模式类装饰器
def singleton(cls, *args, **kw):
    instances = {}

    def getinstance():
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]

    return getinstance


def generate_uuid_filename(filename, rootdir="jeek", path_flag=True):
    """通过uuid生成唯一文件名,并包含日期路径"""

    # 从源文件名中获取文件后缀
    suffix = filename.split(".")
    if len(suffix) > 1:
        suffix = filename.split(".")[1]
    else:
        suffix = "jpg"
    uuid_str = uuid.uuid4().hex
    dayTime = datetime.datetime.now().strftime("%Y/%m/%d")
    path = dayTime if path_flag else ""

    tmp_file_name = "%s/%s/%s.%s" % (rootdir, path, uuid_str, suffix)
    return tmp_file_name


#  生成订单号
def get_order_code():
    #  年月日时分秒+time.time()的后7位
    order_no = str(
        time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
        + str(time.time()).replace(".", "")[-7:]
    )
    return order_no


def get_authcode(software, domain, url):
    timestamp = int(time.time())
    asc = PrpCrypt("TgRfpJTYOy4Vhe99rGZpGwdELEqtvmRb")
    try:
        url = url
        # payload 为传入的参数
        payload = {"timestamp": str(timestamp), "domain": domain, "software": software}
        # json形式，参数用json  unicode(str, errors='replace')
        res = post(url, payload)
        data = res["data"]
        authcode = json.loads(asc.decrypt(data))
    except Exception as e:
        # logger.info("获取授权：", e)
        authcode = {"version_code": 0, "version": "演示版", "description": None}

    return authcode


def post(url, data):
    # 请求头
    headers = {"content-type": "application/json"}
    response = requests.post(url, json=data, headers=headers, timeout=(3.05, 10))
    res = response
    response.close()
    return res.json()


class ExportExcelMixin(object):
    def export_as_excel(self, request, queryset):
        meta = self.model._meta
        field_names = [field.name for field in meta.fields]

        response = HttpResponse(content_type="application/msexcel")
        response["Content-Disposition"] = f"attachment; filename={meta}.xlsx"
        wb = Workbook()
        ws = wb.active
        ws.append(field_names)
        for obj in queryset:
            for field in field_names:
                data = [f"{getattr(obj, field)}" for field in field_names]
            row = ws.append(data)

        wb.save(response)
        return response

    export_as_excel.short_description = "导出Excel"


# 读取yaml配置
def read_yaml_config(yaml_path):
    # 判断文件是否存在不存在创建
    # 获取yaml文件路径
    if os.path.exists(yaml_path):
        with open(file=yaml_path, mode="r", encoding="utf-8") as f:
            input = f.read()
            config = yaml.safe_load(input)
            return config
    else:
        logger.info("host.yaml配置文件不存在")
        return {}


import codecs


# 修改文件编码为utf8,传入要修改的文件对象和编码后文件的存储路径
def change_file_encode_to_utf8(file_path, encoded_file_path):
    # open(encoded_file_path, "wb").write(open(file_path, "rb")
    # .read().decode("unicode_escape").encode("utf8"))

    src = file_path
    dst = encoded_file_path
    source = codecs.open(src, "r").read().decode("string-escape")
    codecs.open(dst, "wb").write(source)
